<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>函数的call/apply/bind()</title>
</head>
<body>

  <!-- 
    1. 区别call()/apply()/bind()
        call(obj)/apply(obj): 调用函数, 指定函数中的this为第一个参数的值
        bind(obj): 返回一个新的函数, 新函数内部会调用原来的函数, 且this为bind()指定的第一参数的值
        注意: 如果obj是null/undefined, this为window
    2. 应用
        call()/bind()应用: 根据伪数组生成真数组
        bind(): react中组件的自定义方法 / vue中的事件回调函数内部
    3. 自定义call()/apply()
        1). 给obj添加一个临时方法, 方法名任意, 值为当前函数
        2). 通过obj调用这个临时方法, 并将接收的参数传入
        3). 删除obj上的这个临时方法属性
    4. 自定义实现bind()
        1). 返回一个新函数
        2). 在新函数内部通过原函数对象的call方法来执行原函数
            指定this为obj
            指定参数为bind调用的参数和后面新函数调用的参数
  -->

  <script src="../dist/190719-utils.js"></script>
  <script>
    /* 
      全局变量: window的属性
      全局函数: window的方法
    */
    function fn(a, b) {
      this.xxx = 3
      console.log(a, b, this, arguments.length)
      return a + b
    }

    fn(1, 2)
    const obj = {m: 0}
    aUtils.call(fn, obj, 10, 20) // obj.fn(1, 2)
    aUtils.apply(fn, obj, [1, 2])
    aUtils.call(fn, null, 1, 2)
    aUtils.bind(fn, obj)(3, 4) // 3, 4 obj 2
    aUtils.bind(fn, obj, 5)(3, 4) // 5 3 obj 3
    aUtils.bind(fn, obj, 5, 6)(3, 4) // 5 6 obj 4

    Function.prototype.call = function () {
      
    }

    fn.call()
  </script>
</html>
